package com.smart.manager.member.repository;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import com.smart.common.entities.core.BaseSearch;
import com.smart.common.entities.core.Page;
import com.smart.manager.member.entities.bodys.RMemberAccount;
import com.smart.manager.member.entities.enums.CoinAccountEvent;
import com.smart.manager.member.entities.enums.EnergyAccountEvent;
import com.smart.manager.member.entities.models.MemberCoinBill;
import com.smart.manager.member.entities.models.MemberEnergy;
import com.smart.manager.member.entities.models.MemberProfileAccount;
import com.smart.manager.member.entities.models.query.QMemberCoinBill;
import com.smart.manager.member.entities.models.query.QMemberProfileAccount;
import com.smart.manager.member.entities.views.MemberView;
import com.smart.utils.SqlUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 商店组织库
 *
 * @author Administrator
 * @date 2023/04/02
 */
@Service
@Log4j2
@RequiredArgsConstructor
public class MemberAccountRepository {


    public Page<MemberProfileAccount> pageList(RMemberAccount.SearchBody search) {
        QMemberProfileAccount query = new QMemberProfileAccount();
        Opt.ofBlankAble(search.getPhoneNumber()).ifPresent(x->query.member.phoneNumber.contains(x));
        Opt.ofBlankAble(search.getNickName()).ifPresent(x->query.member.nickName.contains(x));
        query.order().id.desc();
        query.setFirstRow(search.firstRow()).setMaxRows(search.maxRows());
        return new Page<MemberProfileAccount>().load(query.findPagedList());
    }

    /**
     * 初始化会员账户
     * @param memberId 会员编号
     */
    @Transactional(rollbackFor = Exception.class)
    @Async
    public void initAccount(Long memberId) {
        MemberProfileAccount account = new QMemberProfileAccount().member.id.eq(memberId).setMaxRows(1).findOne();
        Assert.isNull(account, "会员账户开立失败,会员账户已存在了");
        MemberView memberView = new MemberView();
        memberView.setId(memberId);
        new MemberCoinBill().setMember(memberView).setRemark("初始化用户账户").setEvent(CoinAccountEvent.INIT).setOriginalTotal(0).setEventTotal(0).setRemainTotal(0).setEventTime(LocalDateTime.now()).save();
        new MemberProfileAccount().setMember(memberView).setCoinBalance(0).setCashBalance(BigDecimal.ZERO)
                .setMedalBalance(0).setPowerBalance(0).setChickenQuantity(3).setEggQuantity(0).save();
    }

    /**
     * 保存事件
     * @param memberId   会员编号
     * @param event
     * @param eventTotal
     * @param remark
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveEvent(Long memberId, CoinAccountEvent event, int eventTotal, String remark) {
     if(eventTotal<=0) {
         return;
     }
        MemberProfileAccount account = new QMemberProfileAccount().member.id.eq(memberId).setMaxRows(1).findOne();
        Assert.notNull(account, "会员账户查询失败");
        //需要减少的金币事件
        List<CoinAccountEvent> deduct = List.of(CoinAccountEvent.DEDUCT ,CoinAccountEvent.BUYPIG,CoinAccountEvent.SHOPOUT,CoinAccountEvent.AUTOMATIC);
        int eventDbTotal = deduct.contains(event) ? eventTotal * -1 : eventTotal;
        Integer originalTotal = account.getCoinBalance();
        int remainTotal = originalTotal + eventDbTotal;
        MemberCoinBill memberCoinBill = new MemberCoinBill();
        memberCoinBill.setMember(account.getMember()).setRemark(remark).setEvent(event)
                .setOriginalTotal(originalTotal).setEventTotal(eventDbTotal).setRemainTotal(remainTotal)
                .setEventTime(LocalDateTime.now()).save();
        account.setCoinBalance(remainTotal).save();


    }


    @Transactional(rollbackFor = Exception.class)
    public void saveEgg(Long memberId, int eventTotal) {
        Assert.isTrue(eventTotal > 0, "鸡蛋数量必须大于1");
        MemberProfileAccount account = new QMemberProfileAccount().member.id.eq(memberId).setMaxRows(1).findOne();
        Assert.notNull(account, "会员账户查询失败");
        Integer originalTotal = account.getEggQuantity();
        int remainTotal = originalTotal + eventTotal;
        account.setEggQuantity(remainTotal).save();
    }

    /**
     * @param memberId 玩家id
     * @param eventTotal 偷蛋次数
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveStealingEggs(Long memberId, int eventTotal) {
        MemberProfileAccount account = new QMemberProfileAccount().member.id.eq(memberId).setMaxRows(1).findOne();
        Assert.notNull(account, "会员账户查询失败");
        Integer originalTotal = account.getChickenQuantity();
        int remainTotal = originalTotal + eventTotal;
        account.setChickenQuantity(remainTotal).save();
    }

    /**
     * 能量兑换
     * @param memberId
     * @param event
     * @param eventTotal
     * @param remark
     */
    @Transactional(rollbackFor = Exception.class)
    public void savePowerEvent(Long memberId, EnergyAccountEvent event, int eventTotal, String remark) {
        Assert.isTrue(eventTotal > 0, "事件能量必须大于1");
        MemberProfileAccount account = new QMemberProfileAccount().member.id.eq(memberId).setMaxRows(1).findOne();
        Assert.notNull(account, "会员账户查询失败");
        //需要减少的能量事件
        List<EnergyAccountEvent> deduct = List.of(EnergyAccountEvent.DEDUCT ,EnergyAccountEvent.EXCHANGE);
        int eventDbTotal = deduct.contains(event) ? eventTotal * -1 : eventTotal;
        Integer originalTotal = account.getPowerBalance();
        int remainTotal = originalTotal + eventDbTotal;
        MemberEnergy memberCoinBill = new MemberEnergy();
        memberCoinBill.setMember(account.getMember()).setRemark(remark).setEvent(event)
                .setOriginalTotal(originalTotal).setEventTotal(eventDbTotal).setRemainTotal(remainTotal)
                .setEventTime(LocalDateTime.now()).save();
        account.setPowerBalance(remainTotal).save();
    }


    /**
     * @param memberId 获取会员账户信息
     * @return {@code MemberProfileAccount}
     */
    public MemberProfileAccount getAccount(Long memberId) {
        MemberProfileAccount memberProfileAccount = new QMemberProfileAccount().member.id.eq(memberId).setMaxRows(1).findOne();
        Assert.notNull(memberProfileAccount, "会员资料信息不存在");
        return memberProfileAccount;
    }

    /**
     * 查找金币账单列表
     * @param body
     * @return {@code List<MemberCoinBill>}
     */
    public List<MemberCoinBill> findCoinBillList(RMemberAccount.FindBillBody body) {
        QMemberCoinBill query = new QMemberCoinBill().member.id.eq(body.getMemberId());
        Opt.ofBlankAble(body.getDateRange()).ifPresent(x -> {
            LocalDateTime[] times = SqlUtil.formatDateTimeRange(body.getDateRange());
            query.eventTime.between(times[0], times[1]);
        });
        return query.id.desc().findList();
    }


    /**
     * 查询会员金币数据
     *
     * @param memberId 会员编号
     * @param search   搜索条件
     * @return {@code Page<MemberProfileAccount>}
     */
    public Page<MemberCoinBill> getMyCoinBillPage(Long memberId, BaseSearch search) {
        QMemberCoinBill query = new QMemberCoinBill();
        query.member.id.eq(memberId).order().id.desc();
        query.setFirstRow(search.firstRow()).setMaxRows(search.maxRows());

        return new Page<MemberCoinBill>().load(query.findPagedList());
    }
}
